# CTerm class
# Purpose: More user-friendly interpretation of the ATerms from the
#          Stratego C definition
# Author:  Wouter Caarls
# Date:    05-11-2004

import sys, string
from aterm import *
from stratego import *

class CTerm(ATerm):
  """Default class, for literals"""
  def __init__(self, name):
    """Constructor"""
    ATerm.__init__(self, name)

  def name(self):
    """Returns the term's data in lowercase"""
    return string.lower(self.data)

class TypeId(ATerm):
  """Type identifier"""
  def __init__(self, name):
    """Constructor"""
    ATerm.__init__(self, "TypeId", [ATerm("\"" + name + "\"")])

  def name(self):
    """Returns the typename without quotes"""
    return self.children[0].data[1:-1]

class TypeSpec(ATerm):
  """Type specification"""
  def __init__(self, id, prequalifier=ATerm("[]"), postqualifier=ATerm("[]")):
    """Constructor"""
    ATerm.__init__(self, "TypeSpec", [prequalifier, id, postqualifier])

  def prequalifier(self):
    """Returns the prequalifier, a list ATerm"""
    return self.children[0]

  def typeid(self):
    """Returns the type identifier, a TypeID CTerm"""
    return self.children[1]

  def postqualifier(self):
    """Returns the postqualifier, a list ATerm"""
    return self.children[2]

  def name(self):
    """Returns the entire name of the type, including qualifiers"""
    return PPC(self)

class DeclSpec(ATerm):
  """Declaration specification"""
  def __init__(self, storageclass=ATerm("[]"), typespec=ATerm("[]")):
    """Constructor"""
    ATerm.__init__(self, "DeclSpec", [storageclass, typespec])

  def storageclass(self):
    """Returns the storage class, a list ATerm"""
    return self.children[0]

  def typespec(self):
    """Returns the type specifier, a TypeSpec CTerm"""
    return self.children[1]

  def name(self):
    """Returns the entire name of the type, including qualifiers"""
    return PPC(self)

class Id(ATerm):
  """Identifier"""
  def __init__(self, name):
    """Constructor"""
    ATerm.__init__(self, "Id", [ATerm("\"" + name + "\"")])

  def name(self):
    """Returns the identifier's name without quotes"""
    return self.children[0].data[1:-1]
  
class IntConst(ATerm):
  """Integer constant"""
  def __init__(self, value):
    """Constructor"""
    ATerm.__init__(self, "IntConst", [ATerm("\"" + value + "\"")])

  def value(self):
    """Returns the integer value"""
    return int(self.children[0].data[1:-1])

class FloatConst(ATerm):
  """Floating point constant"""
  def __init__(self, value):
    """Constructor"""
    ATerm.__init__(self, "FloatConst", [ATerm("\"" + value + "\"")])

  def value(self):
    """Returns the floating point value"""
    return float(self.children[0].data[1:-1])

class KernelDef(ATerm):
  """Identifier declaration"""
  def __init__(self, sdef, kdef, body):
    """Constructor"""
    ATerm.__init__(self, "KernelDef", [sdef, kdef, body])

  def sdef(self):
    """Returns skeleton definition, an IdDecl CTerm"""
    return self.children[0]

  def kdef(self):
    """Returns kernel definition, an IdDecl CTerm"""
    return self.children[1]

  def body(self):
    """Returns kernel body, a CompoundStm ATerm"""
    return self.children[2]

class IdDecl(ATerm):
  """Identifier declaration"""
  def __init__(self, id, pointer=ATerm("[]"), paramlist=ATerm("None")):
    """Constructor"""
    if paramlist.data == "Some":
      paramlist = paramlist.children[0]

    ATerm.__init__(self, "IdDecl", [pointer, id, paramlist])

  def pointer(self):
    """Returns possible pointers, a list ATerm"""
    return self.children[0]

  def id(self):
    """Returns the identifier, an Id CTerm"""
    return self.children[1]

  def paramlist(self):
    """Returns the parameter list, a ParamList CTerm"""
    return self.children[2]

class ParamDecl(ATerm):
  """Parameter declaration"""
  def __init__(self, typespec, iddecl=ATerm("None"), init=ATerm("None")):
    """Constructor"""
    if iddecl.data == "Some":
      iddecl = iddecl.children[0]

    if init.data == "Some":
      init = init.children[0].children[0]

    ATerm.__init__(self, "ParamDecl", [typespec, iddecl, init])

  def typespec(self):
    """Returns the type specifier, a TypeSpec or DeclSpec CTerm"""
    return self.children[0]

  def iddecl(self):
    """Returns the identifier declaration, an IdDecl CTerm"""
    return self.children[1]

  def init(self):
    """Returns the default value, an ATerm"""
    return self.children[2]

class ParamList(ATerm):
  """Parameter list"""
  def __init__(self, paramdecls=ATerm("[]")):
    """Constructor"""
    ATerm.__init__(self, "ParamList", [paramdecls])

  def paramdecls(self):
    """Returns the list of parameter declarators, a list ATerm of
       ParamDecl CTerms"""
    return self.children[0]

class FunDef(ATerm):
  """Function definition"""
  def __init__(self, iddecl, typespec=ATerm("NoTypeSpecifier"), body=ParseATerm("Compound([], [])")):
    """Constructor"""
    ATerm.__init__(self, "FunDef", [typespec, iddecl, body])

  def typespec(self):
    """Returns the type specifier, a TypeSpec CTerm"""
    return self.children[0]

  def iddecl(self):
    """Returns the identifier declaration, an IdDecl CTerm"""
    return self.children[1]

  def body(self):
    """Returns the function body, a Compound ATerm"""
    return self.children[2]

class FunCall(ATerm):
  """Function call"""
  def __init__(self, id, params=ATerm("[]")):
    """Constructor"""
    ATerm.__init__(self, "FunCall", [id, params])

  def id(self):
    """Returns the function identifier, an Id CTerm"""
    return self.children[0]

  def params(self):
    """Returns the function parameters, a list ATerm"""
    return self.children[1]

class ArrayDecl(ATerm):
  """Array declaration"""
  def __init__(self, end):
    """Constructor"""
    ATerm.__init__(self, "ArrayDecl", [end])

  def start(self):
    """Returns the start of the array (0)"""
    return 0

  def end(self):
    """Returns the end of the array"""
    return self.children[0].evaluate()

class SCArrayDecl(ATerm):
  """Array declaration"""
  def __init__(self, start, end):
    """Constructor"""
    ATerm.__init__(self, "SCArrayDecl", [start, end])

  def start(self):
    """Returns the start of the array"""
    return self.children[0].evaluate()

  def end(self):
    """Returns the end of the array"""
    return self.children[1].evaluate()

def InterpretATerm(t):
  """Interpret an ATerm (tree) into a CTerm (tree). Tries to recognise
     as much ATerms as possible, and leaves the others be.
     Probably an inefficient implementation"""
  if not isinstance(t, ATerm) and not isinstance(t, CTerm):
    raise ValueError, "Not an ATerm"

  for c in range(len(t.children)):
    t.children[c] = InterpretATerm(t.children[c])
  
  ot = t

  if t.data[0] != "\"" and t.children == []:
    # Non-string literal
    t = CTerm(t.data)
  elif t.data == "IntConst":
    t = IntConst(t.children[0].data[1:-1])
  elif t.data == "FloatConst":
    t = FloatConst(t.children[0].data[1:-1])
  elif t.data == "TypeId":
    t = TypeId(t.children[0].data[1:-1])
  elif t.data == "TypeSpec":
    t = TypeSpec(t.children[1], t.children[0], t.children[2])
  elif t.data == "DeclSpec":
    t = DeclSpec(t.children[0], t.children[1])
  elif t.data == "Id":
    t = Id(t.children[0].data[1:-1])
  elif t.data == "IdDecl":
    t = IdDecl(t.children[1], t.children[0], t.children[2])
  elif t.data == "ParamDecl":
    t = ParamDecl(t.children[0], t.children[1], t.children[2])
  elif t.data == "ParamList":
    t = ParamList(t.children[0])
  elif t.data == "FunDef":
    t = FunDef(t.children[1], t.children[0], t.children[2])
  elif t.data == "KernelDef":
    t = KernelDef(t.children[0], t.children[1], t.children[2])
  elif t.data == "FunCall":
    t = FunCall(t.children[0], t.children[1])
  elif t.data == "ArrayDecl":
    t = ArrayDecl(t.children[0])
  elif t.data == "SCArrayDecl":
    t = SCArrayDecl(t.children[0], t.children[1])

  t.annotations = ot.annotations

  return t
